#ifndef PRYN_GUI_MENU_H
#define PRYN_GUI_MENU_H

typedef struct PrynGuiMenu PrynGuiMenu;
typedef unsigned int PrynGuiMenuItem;
typedef uintptr_t PrynGuiMenuData;

#include <pryn/gui/control.h>

#include <pryn/state.h>
#include <pryn/string.h>

/** @defgroup PrynGuiMenu PrynGuiMenu C API
	@{ */

PrynGuiImport (PrynResult, prynGuiMenuCreatePopup, (PrynGuiMenu **menu, PrynState *state)) ///< Create a new popup GUI menu.
PrynGuiImport (PrynResult, prynGuiMenuCreateBar, (PrynGuiMenu **menu, PrynState *state)) ///< Create a new bar GUI menu.
PrynGuiImport (PrynResult, prynGuiMenuDestroy, (PrynGuiMenu *self)) ///< Destroy the GUI menu.
PrynGuiImport (PrynResult, prynGuiMenuDisplay, (PrynGuiMenu *self, int x, int y, PrynGuiControl *parent, PrynGuiMenuItem *selected)) ///< Display the menu. If it was successful, the id of the menu item that was opened is output. Otherwise 0 is output, which may be due to an error or may be because the user clicked away from the menu.
PrynGuiImport (PrynResult, prynGuiMenuDisplayData, (PrynGuiMenu *self, int x, int y, PrynGuiControl *parent, PrynGuiMenuData *selected)) ///< Display the menu, outputting the data field of the item that was returned or 0 for none. 
PrynGuiImport (PrynResult, prynGuiMenuItemData, (PrynGuiMenu *self, PrynGuiMenuItem id, PrynGuiMenuData *output)) ///< Return the data field for a menu item, or 0 on failure.

PrynGuiImport (PrynResult, prynGuiMenuAppendItem, (PrynGuiMenu *self, const PrynString *label, PrynGuiMenuData data, PrynGuiMenuItem *output)) ///< Append a text item to the menu.

PrynGuiImport (PrynResult, prynGuiMenuState, (PrynGuiMenu *menu, PrynState **output)); ///< Retrieve the state the menu exists within, or 0 on failure.

/// Append a literal string item to the menu.
#define prynGuiMenuAppendItemLiteral(MENU, LABEL, DATA, OUTPUT)  prynStringLiteralBlock (NAME, STRING, { prynGuiMenuAppendItem ((MENU), &STRING, DATA, OUTPUT); })

#ifdef PrynGuiInternalStructs
/// A popup menu.
struct PrynGuiMenu
{
#ifdef PrynGuiInternal
	PrynState *pState; ///< State information.
	void *pPlatform; ///< Platform-specific information about the menu.
	PrynGuiMenuItem pItemCount; ///< Number of items on the menu.
#endif /* PrynGuiInternal */

#ifdef __cplusplus
	static inline PrynGuiMenu *CreatePopup (PrynState *state) { PrynGuiMenu *result; state->checkError (prynGuiMenuCreatePopup (&result, state)); return result; } ///< Create a new popup GUI menu.

	static inline PrynGuiMenu *CreateBar (PrynState *state) { PrynGuiMenu *result; state->checkError (prynGuiMenuCreateBar (&result, state)); return result; } ///< Create a new bar GUI menu.

	inline PrynResult checkError (PrynResult result) { return prynCheckErrorBase (state (), result); } ///< If the result is below zero, throw an error.

	inline void destroy () { checkError (prynGuiMenuDestroy (this)); } ///< Destroy the GUI menu.

	PrynGuiMenuItem display (int x, int y, PrynGuiControl *parent) { PrynGuiMenuItem result; checkError (prynGuiMenuDisplay (this, x, y, parent, &result)); return result; } ///< Display the menu. If it was successful, the id of the menu item that was opened is returned. Otherwise 0 is returned because the user clicked away from the menu.
	PrynGuiMenuData displayData (int x, int y, PrynGuiControl *parent) { PrynGuiMenuData result; checkError (prynGuiMenuDisplayData (this, x, y, parent, &result)); return result; } ///< Display the menu, returning the data field of the item that was returned or 0 for none. 

	PrynGuiMenuData itemData (PrynGuiMenuItem id) { PrynGuiMenuData output; checkError (prynGuiMenuItemData (this, id, &output)); return output; } ///< Return the data field for a menu item.

	PrynGuiMenuItem appendItem (const PrynString &label, PrynGuiMenuData data = 0) { PrynGuiMenuItem result; checkError (prynGuiMenuAppendItem (this,& label, data, &result)); return result; } ///< Append a text item to the menu. The string is copied away.

	PrynState *state () { PrynState *result; prynCheckErrorNull (prynGuiMenuState (this, &result)); return result; } ///< Return the state the menu exists within.

#endif /* __cplusplus */
};
#endif /* PrynGuiInternalStructs */

/** @} */

#endif /* PRYN_GUI_MENU_H */
